package com.hdax.dmw.utils;

import cn.hutool.crypto.asymmetric.RSA;
import com.hdax.dmw.exceptions.user.TokenException;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class TokenUtil {

    //私钥 RS256
    private static final String PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDOBl2L0/gDtOKw28IKvZ7i8wJIQBDs5xzQK81eWj8+XKNMRjI/Wypzybd+7BI0m/PnsztNxorg7lNwyhLOOMdjtNQfAEtJV+soQyC9MqzbjTWgbCVzKcVbrR12xV7nhriXG2pVOrj2Oz1jWDnAlCTcslhg9+sD0+cwW1pyOj3Mu00huQXBGYbI9AJ3SxMJEEBWHRx4480IGIvpHxz0PwNE4Ao02kINnLFPqIxFLrXVYNsVd5z0lYioHsI1dsWIxRii+g/HGZ29+5b3tzWKRXFFescGRHR2SuJy/QoVAu4u7abi7g/9p7cswhPUjKOJcjQyQlhwTRhtl1klQMo7/c3ZAgMBAAECggEAEa4KKQ2vouHK8lJpfHJ5SBCCiaC10x6iIlsf7JDiDH/2o30Cot0372fID2RCy7D2ZVPEKxB2qobJMkylAH1u3ueNrHth+pFI5NOd456NpumfSHz/Wbqj7RIWDTMyybuN66m2nknDxZ2fzv6rNhOAdk/3tZqQ2Gs+06+DO3o0A3WH5T+Q+fkrSQLfccOEvuM2TILTby26eggXMDh9XArqRyVK9vdPVYsZZPZNdh7TOvFAiPEWX298oiJpwzsCexoZRFven2MeujN1HcBod2kcGrnASZ3nK6t4obsqX7F6kpwitxFXGhRmHLkJv4lIiDELezrq59xdey90e50zCZRCYQKBgQDpJx2LD9YpOxp0u+gt8N6+r4J00Jsl72EllMY5t6Gk81wmhoB6HRKGWdyhjQ2eqKKRF/Zzxsq51DtUoS3hhvuqGnzl03vUWxL3vqk+3ykXJC6ULGEOOyOvHnuhWovmaUoMaal7iRFapYyL7PtjY8WTQB1N9gGZfYlt9FNUOb/YnwKBgQDiNreZk04M+hZYt/lbsvXpz7PItD95OV+VSoecBUA4t39saLGekb+/KvoN10BYpFiIKSEONSw3RBdTGnCwBNsTkKFxiqkpR9yizzLS/VZ05yF0nBCEv5W1GJyIpM31vgz3L+NvJ/SrImCSEyC5V9sSuzr5maUy2Z3GRZuWeVouhwKBgQDbRIASQiiEyiLNWdK3MeoppuGnfnAKsx/HuizaJwqMGJq3WJMHRMQhOe22uPLwHWQV1FVg+Lm7Hg9WPebqTIntpc+ETOoOAkDKYbLFgBYiv1JW4427Vn7uuFpImuErJiYPmmdb2MJLX5nYFl0tUa2EGC33Hb7PXTKcB8U+VrlHvQKBgGc61xATQ7PyUE5OLlHlWglHymBVuP2F7BOBvl65mrQHMPP01tFo65q+bvvv9aI95VTFiBsmsrXJsecvkqsQnDTSdIoO3+FBtPLrIONdzp1seDzxlywtDZFl2NEWfBKfluUaimxITIPoHS+r4OwTpppmrKQItHV/D1vSmgzR9hBzAoGAQ0rDGIk4NcRhwwW7GUjv4MwxIQuQ2NrlTb+NoLmYCi+Q9KVhdjuG1tqc2nDGlX5TgYeUtVyRFRQjJCAK5UcxIhjCVhE1g8hO1/c3Z3Ze4hTH9b43TXwwSPYGdSYcRniC16Jcff+t+IcyLdmfU18c+kk/nUp4CJSV7LHwiX3pL+8=";
    //公钥
    private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzgZdi9P4A7TisNvCCr2e4vMCSEAQ7Occ0CvNXlo/PlyjTEYyP1sqc8m3fuwSNJvz57M7TcaK4O5TcMoSzjjHY7TUHwBLSVfrKEMgvTKs2401oGwlcynFW60ddsVe54a4lxtqVTq49js9Y1g5wJQk3LJYYPfrA9PnMFtacjo9zLtNIbkFwRmGyPQCd0sTCRBAVh0ceOPNCBiL6R8c9D8DROAKNNpCDZyxT6iMRS611WDbFXec9JWIqB7CNXbFiMUYovoPxxmdvfuW97c1ikVxRXrHBkR0dkricv0KFQLuLu2m4u4P/ae3LMIT1IyjiXI0MkJYcE0YbZdZJUDKO/3N2QIDAQAB";

    public static final Long TOKEN_EXPIRE_TIME =2 * 60 * 60 * 1000L;

    //生成token
    public static String createToken(Map<String,Object> params){
        //非对称加密
        //(服务器)生成token的时候需要提供 私钥
        RSA rsa = new RSA(PRIVATE_KEY,null);
        PrivateKey privateKey = rsa.getPrivateKey();
        Date now = new Date();
        JwtBuilder builder = Jwts.builder()
                .claim("account",params.get("account"))
                .claim("nickName",params.get("nickName"))
                .setSubject(params.get("account").toString())
                .setIssuedAt(now)
                .setExpiration(new Date(now.getTime() + TOKEN_EXPIRE_TIME))
                .signWith(privateKey, SignatureAlgorithm.RS256)
                .setId(params.get("id").toString());
        return builder.compact();
    }

    //解析token
    public static Map<String,String> parseToken(String token) throws TokenException {
        Map<String, String> result = new HashMap<>();
        JwtParserBuilder parserBuilder = Jwts.parserBuilder();
        RSA rsa = new RSA(null,PUBLIC_KEY);
        PublicKey publicKey = rsa.getPublicKey();
        parserBuilder.setSigningKey(publicKey);
        JwtParser jwtParser = parserBuilder.build();
        Long userId = 0L;
        try{
            Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
            Claims claims = claimsJws.getBody();
            userId = Long.parseLong(claims.getId());
            result.put("id", claims.getId());
            result.put("account",claims.get("account",String.class));
            result.put("nickName",claims.get("nickName", String.class));
            return result;
        }catch (ExpiredJwtException exception){
            log.error("[JWT] token has been expired! expire info: [{}]",exception.getMessage());
            throw exception;
            //throw new TokenException(ServiceResultEnum.ADMIN_TOKEN_EXPIRE_ERROR);
        }
        catch (Exception exception){
            throw new TokenException(ServiceResultEnum.OPERATE_ERROR.getCode(),ServiceResultEnum.OPERATE_ERROR.getResult());
        }
    }
}
